package com.yixun.qfbao.exception;

import javax.validation.ConstraintViolationException;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import com.yixun.qfbao.response.CommonResponse;
import com.yixun.qfbao.util.exception.TServerException;

@ControllerAdvice(basePackages = "com.yixun.qfbao")
public class GlobalException {

    private static final Logger LOGGER = LoggerFactory.getLogger(GlobalException.class);

    @ExceptionHandler(value = Exception.class)
    @ResponseBody
    public Object defaultError(Exception ex){
        CommonResponse commonResponse = new CommonResponse();
        String message = null;
        if(ex instanceof ChannelException){
            message = ex.getMessage();
            commonResponse.setCode(ResponseCode.SYSTEM_EXCEPTION.getCode());
            if(StringUtils.isNotBlank(message)){
                commonResponse.setMsg(message);
            }else{
                commonResponse.setCode(ResponseCode.SYSTEM_EXCEPTION.getMessageTemplate());
            }
            LOGGER.error("GlobalException -> ChannelException: {}", ex);
        }else if(ex instanceof TServerException){
            String errorCode = ((TServerException) ex).getErrorCode();
            String errorMsg = ((TServerException) ex).getErrorMsg();
            if (StringUtils.isEmpty(errorCode)) {
                errorCode = ResponseCode.SYSTEM_EXCEPTION.getCode();
            }
            commonResponse.setCode(errorCode);
            commonResponse.setMsg(errorMsg);
            LOGGER.error("GlobalException -> TServerException: {}", ex);
        }else if(ex instanceof BindException) {
            message = ex.getMessage();
            commonResponse.setCode(ResponseCode.PARAM_INVALID.getCode());
            if(StringUtils.isNotBlank(message)){
                commonResponse.setMsg(message);
            }else{
                commonResponse.setCode(ResponseCode.PARAM_INVALID.getMessageTemplate());
            }
            LOGGER.error("GlobalException -> paramsError --> BindException: {}", ex);
        }else if (ex instanceof MethodArgumentNotValidException) {
            BindingResult bindingResult = ((MethodArgumentNotValidException) ex).getBindingResult();
            // getFieldError获取的是第一个不合法的参数(P.S.如果有多个参数不合法的话)
            FieldError fieldError = bindingResult.getFieldError();
            message = ex.getMessage();
            if (fieldError != null) {
                message = fieldError.getDefaultMessage();
            }
            commonResponse.setCode(ResponseCode.PARAM_INVALID.getCode());
            if(StringUtils.isNotBlank(message)){
                commonResponse.setMsg(message);
            }else{
                commonResponse.setCode(ResponseCode.PARAM_INVALID.getMessageTemplate());
            }
            LOGGER.error("GlobalException -> paramsError --> MethodArgumentNotValidException: {}", ex);
        } else if (ex instanceof ConstraintViolationException) {
            /*
             * ConstraintViolationException的e.getMessage()形如
             *     {方法名}.{参数名}: {message}
             *  这里只需要取后面的message即可
             */
            message = ex.getMessage();
            if (StringUtils.isNotBlank(message)) {
                int lastIndex = message.lastIndexOf(':');
                if (lastIndex >= 0) {
                    message = message.substring(lastIndex + 1).trim();
                }
            }
            commonResponse.setCode(ResponseCode.PARAM_INVALID.getCode());
            if(StringUtils.isNotBlank(message)){
                commonResponse.setMsg(message);
            }else{
                commonResponse.setCode(ResponseCode.PARAM_INVALID.getMessageTemplate());
            }
            LOGGER.error("GlobalException -> paramsError --> ConstraintViolationException: {}", ex);
        }else{
            commonResponse.setCode(ResponseCode.SYSTEM_EXCEPTION.getCode());
            if(StringUtils.isNotBlank(ex.getMessage())){
                commonResponse.setMsg(ex.getMessage());
            }else{
                commonResponse.setCode(ResponseCode.SYSTEM_EXCEPTION.getMessageTemplate());
            }
            LOGGER.error("GlobalException -> Exception: {}", ex);
        }
        return commonResponse;
    }
}
